/*
********************************************************************************
* 文件: findstr.h
* 模块: lexcial
* 代词: le_
* 
* 
* 作用：是词法分析的辅助函数，主要对机器指令的助记符进行识别、对伪指令的助记符进行识别，
*      对数字进行识别。
* 版本：
********************************************************************************
*/


#include <stdlib.h>
#include "character.h"

#include "lexical.h"
/*
********************************************************************************
* 数据定义，实际是一种变形的二叉树。
* 结点定义如下：
*    四字节的 bit map, 其中 bit0 对应字串结束，bit1 对应字符 A, bit2 对应字符 B ...
*    bit 27 对应下划线， bit 28 对应 xxx， bit29 对应 xxx， bit 30 对应 xxx,
*    bit 31 对应 xxx
********************************************************************************
*/
struct  _inst_table
{
    byte  val;
    byte  len;
    byte * str;
};

typedef  struct _inst_table  inst_table;

/*
 *       high byte : 0x06 : 没有使用。
 *  middle hi byte : 0xXX : 类别，根据不同的操作数划分。
 *  middle lo byte : 0xXX : 操作码，两个操作码时，这里是比较小的数。
 *        low byte : 0x00 : 没有使用。
 */

/*
 *  类别 :  
 *     1 : op  $x
 *     2 : 
 *
 */ 
inst_table  ins_table[] = 
  { { INS_BN,      2, "BN"      },
    { INS_BP,      2, "BP"      },
    { INS_BZ,      2, "BZ"      },
    { INS_GO,      2, "GO"      },
    { INS_OR,      2, "OR"      },
    { INS_SL,      2, "SL"      },
    { INS_SR,      2, "SR"      },
    { INS_BEV,     3, "BEV"     },
    { INS_BNN,     3, "BNN"     },
    { INS_BNP,     3, "BNP"     },
    { INS_BNZ,     3, "BNZ"     },
    { INS_BOD,     3, "BOD"     },
    { INS_ADD,     3, "ADD"     },
    { INS_AND,     3, "AND"     },
    { INS_CMP,     3, "CMP"     },
    { INS_CSN,     3, "CSN"     },
    { INS_CSP,     3, "CSP"     },
    { INS_CSZ,     3, "CSZ"     },
    { INS_DIV,     3, "DIV"     },
    { INS_FIX,     3, "FIX"     },
    { INS_FUN,     3, "FUN"     },
    { INS_GET,     3, "GET"     },
    { INS_JMP,     3, "JMP"     },    /* opcode, 0,0, 0  */
    { INS_LDB,     3, "LDB"     },
    { INS_LDO,     3, "LDO"     },
    { INS_LDT,     3, "LDT"     },
    { INS_LDW,     3, "LDW"     },
    { INS_MOR,     3, "MOR"     },
    { INS_MUL,     3, "MUL"     },
    { INS_MUX,     3, "MUX"     },
    { INS_NEG,     3, "NEG"     },
    { INS_NOR,     3, "NOR"     },
    { INS_ORH,     3, "ORH"     },
    { INS_ORL,     3, "ORL"     },
    { INS_ORN,     3, "ORN"     },
    { INS_PBN,     3, "PBN"     },
    { INS_PBP,     3, "PBP"     },
    { INS_PBZ,     3, "PBZ"     },
    { INS_POP,     3, "POP"     },    /* opcode, 0,0, << 16  */
    { INS_PUT,     3, "PUT"     },
    { INS_SLU,     3, "SLU"     },
    { INS_SRU,     3, "SRU"     },
    { INS_STB,     3, "STB"     },
    { INS_STO,     3, "STO"     },
    { INS_STT,     3, "STT"     },
    { INS_STW,     3, "STW"     },
    { INS_SUB,     3, "SUB"     },
    { INS_XOR,     3, "XOR"     },
    { INS_ZSN,     3, "ZSN"     },
    { INS_ZSP,     3, "ZSP"     },
    { INS_ZSZ,     3, "ZSZ"     },
    { INS_FIXU,    4, "FIXU"    },
    { INS_FLOT,    4, "FLOT"    },
    { INS_FDIV,    4, "FDIV"    },
    { INS_FEQL,    4, "FEQL"    },
    { INS_FINT,    4, "FINT"    },
    { INS_FMUL,    4, "FMUL"    },
    { INS_FREM,    4, "FREM"    },
    { INS_FSUB,    4, "FSUB"    },
    { INS_CSNN,    4, "CSNN"    },
    { INS_CSNP,    4, "CSNP"    },
    { INS_CSNZ,    4, "CSNZ"    },
    { INS_CSOD,    4, "CSOD"    },
    { INS_DIVU,    4, "DIVU"    },
    { INS_CMPU,    4, "CMPU"    },
    { INS_CSEV,    4, "CSEV"    },
    { INS_ADDU,    4, "ADDU"    },
    { INS_ANDH,    4, "ANDH"    },
    { INS_ANDL,    4, "ANDL"    },
    { INS_ANDN,    4, "ANDN"    },
    { INS_BDIF,    4, "BDIF"    },
    { INS_FADD,    4, "FADD"    },
    { INS_FCMP,    4, "FCMP"    },
    { INS_FUNE,    4, "FUNE"    },
    { INS_GETA,    4, "GETA"    },
    { INS_INCH,    4, "INCH"    },
    { INS_INCL,    4, "INCL"    },
    { INS_LDBU,    4, "LDBU"    },
    { INS_LDHT,    4, "LDHT"    },
    { INS_LDOU,    4, "LDOU"    },
    { INS_LDSF,    4, "LDSF"    },
    { INS_LDTU,    4, "LDTU"    },
    { INS_LDWU,    4, "LDWU"    },
    { INS_MULU,    4, "MULU"    },
    { INS_MXOR,    4, "MXOR"    },
    { INS_NAND,    4, "NAND"    },
    { INS_NEGU,    4, "NEGU"    },
    { INS_NXOR,    4, "NXOR"    },
    { INS_ODIF,    4, "ODIF"    },
    { INS_ORMH,    4, "ORMH"    },
    { INS_ORML,    4, "ORML"    },
    { INS_PBEV,    4, "PBEV"    },
    { INS_PBNN,    4, "PBNN"    },
    { INS_PBNP,    4, "PBNP"    },
    { INS_PBNZ,    4, "PBNZ"    },
    { INS_PBOD,    4, "PBOD"    },
    { INS_SADD,    4, "SADD"    },
    { INS_SAVE,    4, "SAVE"    },    /* opcode, 0,0, << 16  */
    { INS_SETH,    4, "SETH"    },
    { INS_SETL,    4, "SETL"    },
    { INS_STBU,    4, "STBU"    },
    { INS_STCO,    4, "STCO"    },
    { INS_STHT,    4, "STHT"    },
    { INS_STOU,    4, "STOU"    },
    { INS_STSF,    4, "STSF"    },
    { INS_STTU,    4, "STTU"    },
    { INS_STWU,    4, "STWU"    },
    { INS_SUBU,    4, "SUBU"    },
    { INS_SWYM,    4, "SWYM"    },
    { INS_SYNC,    4, "SYNC"    },    /* opcode, 0,0, 24 : 立即数不能超过 2^24 */
    { INS_TDIF,    4, "TDIF"    },
    { INS_TRAP,    4, "TRAP"    },
    { INS_TRIP,    4, "TRIP"    },
    { INS_WDIF,    4, "WDIF"    },
    { INS_ZSEV,    4, "ZSEV"    },
    { INS_ZSNN,    4, "ZSNN"    },
    { INS_ZSNP,    4, "ZSNP"    },
    { INS_ZSNZ,    4, "ZSNZ"    },
    { INS_ZSOD,    4, "ZSOD"    },
    { INS_FCMPE,   5, "FCMPE"   },
    { INS_FLOTU,   5, "FLOTU"   },
    { INS_CSWAP,   5, "CSWAP"   },
    { INS_2ADDU,   5, "2ADDU"   },
    { INS_4ADDU,   5, "4ADDU"   },
    { INS_8ADDU,   5, "8ADDU"   },
    { INS_ANDMH,   5, "ANDMH"   },
    { INS_ANDML,   5, "ANDML"   },
    { INS_FEQLE,   5, "FEQLE"   },
    { INS_FSQRT,   5, "FSQRT"   },
    { INS_INCMH,   5, "INCMH"   },
    { INS_INCML,   5, "INCML"   },
    { INS_LDUNC,   5, "LDUNC"   },
    { INS_LDVTS,   5, "LDVTS"   },
    { INS_PREGO,   5, "PREGO"   },
    { INS_PRELD,   5, "PRELD"   },
    { INS_PREST,   5, "PREST"   },
    { INS_PUSHJ,   5, "PUSHJ"   },
    { INS_SETMH,   5, "SETMH"   },
    { INS_SETML,   5, "SETML"   },
    { INS_SFLOT,   5, "SFLOT"   },
    { INS_STUNC,   5, "STUNC"   },
    { INS_SYNCD,   5, "SYNCD"   },
    { INS_16ADDU,  6, "16ADDU"  },
    { INS_PUSHGO,  6, "PUSHGO"  },
    { INS_RESUME,  6, "RESUME"  },      /* opcode, 0,0, 8 : 立即数不能大于等于 2^8  */
    { INS_SFLOTU,  6, "SFLOTU"  },
    { INS_SYNCID,  6, "SYNCID"  },
    { INS_UNSAVE,  6, "UNSAVE"  } };    /* opcode, 0,0, << 0  */

inst_table  psu_table[] = 
   { { CMD_WEAK,        4, "weak",         },
     { CMD_BYTE,        4, "byte",         },
     { CMD_WYDE,        4, "wyde",         },
     { CMD_OCTA,        4, "octa",         },
     { CMD_PARAM,       5, "param",        },
     { CMD_LOCAL,       5, "local",        },
     { CMD_ALIGN,       5, "align",        },
     { CMD_TETRA,       5, "tetra",        },
     { CMD_GLOBAL,      6, "global",       },
     { CMD_EXTERN,      6, "extern",       },
     { CMD_SINGLE,      6, "single",       },
     { CMD_DOUBLE,      6, "double",       },
     { CMD_SECTION,     7, "section",      },
     { CMD_STR_UTF8,    8, "str_utf8",     },
     { CMD_RES_BYTE,    8, "res_byte",     },
     { CMD_RES_WYDE,    8, "res_wyde",     },
     { CMD_RES_OCTA,    8, "res_octa",     },
     { CMD_STR_ASCII,   9, "str_ascii",    },
     { CMD_STR_UTF16,   9, "str_utf16",    },
     { CMD_STR_UTF32,   9, "str_utf32",    },
     { CMD_RES_TETRA,   9, "res_tetra",    },
     { CMD_STR_GB2312,  10, "str_gb2312",  },
     { CMD_RES_SINGLE,  10, "res_single",  },
     { CMD_RES_DOUBLE,  10, "res_double",  },
     { CMD_STR_GB18030, 11, "str_gb18030", } };


inst_table  sreg_table[] = 
   { { SRG_rA, 2,  "rA"  },
     { SRG_rB, 2,  "rB"  },
     { SRG_rC, 2,  "rC"  },
     { SRG_rD, 2,  "rD"  },
     { SRG_rE, 2,  "rE"  },
     { SRG_rF, 2,  "rF"  },
     { SRG_rG, 2,  "rG"  },
     { SRG_rH, 2,  "rH"  },
     { SRG_rI, 2,  "rI"  },
     { SRG_rJ, 2,  "rJ"  },
     { SRG_rK, 2,  "rK"  },
     { SRG_rL, 2,  "rL"  },
     { SRG_rM, 2,  "rM"  },
     { SRG_rN, 2,  "rN"  },
     { SRG_rO, 2,  "rO"  },
     { SRG_rP, 2,  "rP"  },
     { SRG_rQ, 2,  "rQ"  },
     { SRG_rR, 2,  "rR"  },
     { SRG_rS, 2,  "rS"  },
     { SRG_rT, 2,  "rT"  },
     { SRG_rU, 2,  "rU"  },
     { SRG_rV, 2,  "rV"  },
     { SRG_rW, 2,  "rW"  },
     { SRG_rX, 2,  "rX"  },
     { SRG_rY, 2,  "rY"  },
     { SRG_rZ, 2,  "rZ"  },
     { SRG_rBB, 3, "rBB"  },
     { SRG_rTT, 3, "rTT"  },
     { SRG_rWW, 3, "rWW"  },
     { SRG_rXX, 3, "rXX"  },
     { SRG_rYY, 3, "rYY"  },
     { SRG_rZZ, 3, "rZZ"  }  };
     

inst_table  const_table[] = 
   { { CNT_UP,         2, "up"    },
     { CNT_BSS,        3, "bss"   },
     { CNT_OFF,        3, "off"   },
     { CNT_DOWN,       4, "down"  },
     { CNT_NEAR,       4, "near"  },
     { CNT_TEXT,       4, "text"  },
     { CNT_DATA,       4, "data"  },
     { CNT_NOTE,       4, "note"  },
     { CNT_SNAN,       4, "sNaN"  },
     { CNT_QNAN,       4, "qNaN"  },
     { CNT_ZERO,       4, "zero"  },
     { CNT_INFINITE,   8, "infinite"  },
     { CNT_DENORMAL,   8, "denormal"  }  };



tetra  find_in_table( inst_table * tbl, tetra tblsize, tetra * str,  tetra  len )
{
    tetra  i, k;

    if( len == 0 )
    {
        return 0xffffffff;
    }
    
    for( i=0; i<tblsize; i++ )
    {
        if( len == tbl[i].len )
        {
            for( k=0; k<len; k++ )
            {
                if( tbl[i].str[k] != str[k] )
                {
                    break;
                }
            }

            if( k == len )
            {
                return  tbl[i].val;
            }
        }
        else if( len < tbl[i].len )
        {
            return 0xffffffff;
        }
    }

    return 0xffffffff;

}



/*
********************************************************************************
* find_instruction
* 作用: 检查输入字符串，识别出它是否是个 instruction.
* 返回: 如果不是一个 instruction ，返回 0 。
*      否则返回这个 instruction 的码值。
* 输入: utf32 形式的字符串，0 表示字符串结束，允许的值可...
*
********************************************************************************
*/
tetra  find_instruction( tetra * str, tetra  len )
{
    tetra  temp;
    
    temp = sizeof(ins_table)/sizeof(inst_table);
    return find_in_table( ins_table, temp, str, len );
}



/*
********************************************************************************
* find_pseudo
* 作用: 检查输入字符串，识别出它是否是个 pseudo.
* 返回: 如果不是一个 pseudo ，返回 0 。
*      否则返回这个 pseudo 的码值。
* 输入: utf32 形式的字符串，0 表示字符串结束，允许的值可...
*
********************************************************************************
*/

tetra  find_pseudo( tetra * str, tetra  len )
{
    tetra  temp;
    
    temp = sizeof(psu_table)/sizeof(inst_table);
    return find_in_table( psu_table, temp, str, len );
}


tetra  find_sreg( tetra * str, tetra  len )
{
    tetra  temp;

    temp = sizeof(sreg_table)/sizeof(inst_table);
    return find_in_table( sreg_table, temp, str, len );
} 


tetra  find_const( tetra * str, tetra  len )
{
    tetra  temp;

    temp = sizeof(const_table)/sizeof(inst_table);
    return find_in_table( const_table, temp, str, len );
}

